package com.minimalist.application.config.satoken;

import cn.dev33.satoken.interceptor.SaInterceptor;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.util.ObjectUtil;
import com.minimalist.basic.config.interceptor.DynamicRateLimitInterceptor;
import com.minimalist.basic.config.interceptor.IpBasedRateLimitInterceptor;
import com.minimalist.basic.config.interceptor.TraceIdInterceptor;
import com.minimalist.basic.config.request.TenantIdContext;
import com.minimalist.basic.config.request.UserIdContext;
import com.minimalist.basic.entity.vo.user.UserVO;
import com.minimalist.basic.service.UserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @author 11987
 */
@Configuration
@Slf4j
public class SaTokenConfigure implements WebMvcConfigurer {
    @Resource
    private UserService userService;
    @Resource
    private TraceIdInterceptor traceIdInterceptor;

    @Resource
    private IpBasedRateLimitInterceptor ipBasedRateLimitInterceptor;

    @Resource
    private DynamicRateLimitInterceptor dynamicRateLimitInterceptor;

    /**
     * 注册 Sa-Token 拦截器
     */
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        /** 演示环境，可以删除 ------- start */
//        SaInterceptor saInterceptor = new SaInterceptor(handle -> {
//            //校验登录
//            StpUtil.checkLogin();
//            // 根据请求类型匹配
//            SaRouter.match(SaHttpMethod.POST, SaHttpMethod.DELETE, SaHttpMethod.PUT)
//                    .check(() -> {
//                        throw new BusinessException("演示环境，只能查询，不能进行操作");
//                    });
//        });
//        registry.addInterceptor(saInterceptor).addPathPatterns("/**")
//                .excludePathPatterns("/basic/user/logout");
        /** 演示环境，可以删除 ------- end */

        //全局拦截配置，必须登陆后才可访问，如果某个接口需要跳过拦截，需要在接口上增加@SaIgnore注解
        SaInterceptor saInterceptor = new SaInterceptor(handle -> {
            if (handle.toString().contains("error")) {
                return;
            }
            log.info("SA-TOKEN 拦截器执行: {}", handle);
            // 检查是否已经登录
            if (StpUtil.isLogin()) {
                SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
                // 确保tokenInfo和loginId不为空
                if (ObjectUtil.isNotNull(tokenInfo) && ObjectUtil.isNotNull(tokenInfo.getLoginId())) {
                    long userId = StpUtil.getLoginIdAsLong();
                    UserIdContext.setUserId(userId);
                    UserVO user = userService.getUserByUserId(userId);
                    if (ObjectUtil.isNull(user)) {
                        // 如果用户不存在，执行相应的处理
                        StpUtil.logout();
                    } else {
                        // 设置租户ID
                        TenantIdContext.setTenantId(user.getTenantId());
                    }
                }
            } else {
                // 如果未登录，执行相应的处理
                StpUtil.checkLogin();
            }
        });
        registry.addInterceptor(saInterceptor).addPathPatterns("/**")
                .excludePathPatterns("/actuator/**").excludePathPatterns("/*/actuator/**")
                .excludePathPatterns("/druid/**").excludePathPatterns("/*/druid/**")
                .excludePathPatterns("/rocketmq/**").excludePathPatterns("/*/rocketmq/**");
        registry.addInterceptor(traceIdInterceptor).addPathPatterns("/**");
        registry.addInterceptor(ipBasedRateLimitInterceptor).addPathPatterns("/**");
        registry.addInterceptor(dynamicRateLimitInterceptor).addPathPatterns("/**");
    }
}

